/**
*********************************************************************************************************
*               Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved.
*********************************************************************************************************
* @file      dataTrans_queue.h
* @brief    queue for receive data from IO peripheral.
* @details
* @author    elliot chen
* @date      2017-04-27
* @version   v1.0
* *********************************************************************************************************
*/

#ifndef __DATATRANS_QUEUE_H
#define __DATATRANS_QUEUE_H

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "string.h"
#include "asr_rtl8763bo_port.h"

/* Defines ------------------------------------------------------------------*/
#define LOOP_QUEUE_MAX_SIZE             (4096)
#define QUEUE_CAPABILITY                (LOOP_QUEUE_MAX_SIZE-1)
/**
 * @brief Enable print log or not
 */

#ifdef PRINT_DATATRANS_QUEUE_LOG
#include "trace.h"
#define DATATRANS_QUEUE_BUFFER(MODULE, LEVEL, pFormat, para_num,...) DBG_BUFFER_##LEVEL(TYPE_BEE2, SUBTYPE_FORMAT, MODULE, pFormat, para_num, ##__VA_ARGS__)
#else
#define DATATRANS_QUEUE_BUFFER(MODULE, LEVEL, pFormat, para_num,...) ((void)0)
#endif

/**
 * @brief write Loop queue function type
 */
typedef uint16_t (*WriteQueueFnCB)(void *, void *, uint16_t);

/**
  * @brief  write queue status
  */
typedef enum
{
    QUEUE_WRITE_OK          = 0,
    QUEUE_WRITE_OVERFLOW    = 1,
    QUEUE_WRTIE_CB_NULL     = 2
} QUEUE_WRITE_STAT;


/**
 * @brief Loop queue data struct
 */
typedef struct
{
    volatile uint16_t   readIndex;          /* index of read queue */
    volatile uint16_t   writeIndex;         /* index of write queue */
    volatile bool       overFlow;           /* loop queue overflow or not */
    uint8_t buf[LOOP_QUEUE_MAX_SIZE];       /* Buffer for loop queue */
} LoopQueue_TypeDef;

/**
  * @brief Exported function
  */
void DataTrans_RegisterPeriphReadFnCB(WriteQueueFnCB pFunc);
void DataTrans_InitQueue(void);
QUEUE_WRITE_STAT DataTrans_WriteQueue(void *peri, uint16_t len);
uint16_t DataTrans_GetFIFOLen(void);
void DataTrans_ReadQueue(uint8_t *pBuf, uint16_t len);
void DataTrans_CopyBuf(uint8_t *pBuf, uint16_t len);
uint16_t DataTrans_FindData(uint8_t data, uint16_t len);
bool DataTrans_QueueIsEmpty(void);

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

#define TX_RBUF_RWSYNC_ENABLE    0
#define RX_RBUF_RWSYNC_ENABLE    0

#if RX_RBUF_RWSYNC_ENABLE == 1

extern u8 RxWaitUsedFlag;
extern u8 RxWaitAvailableFlag;
extern bool bRxWaitUsed;
extern bool bRxWaitAvailable;

#endif

#if TX_RBUF_RWSYNC_ENABLE == 1

extern u8 TxWaitUsedFlag;
extern u8 TxWaitAvailableFlag;
extern bool bTxWaitUsed;
extern bool bTxWaitAvailable;

#endif

enum {
    RBUF_HAS_AVAILABLE_SIZE =  (1<<0),
    RBUF_CLEAR =  (1<<1),
};


typedef enum {
    RBUF_MODE_BLOCKING = 0,
    RBUF_MODE_OVERWRITE
} rbuf_mode_t;


struct _rbuf_s {
    uint8_t *buf;        // the buffer
    int size;           // buffer size
    int used;           // used size
    int rfx;            // read offset
    int wfx;            // write offset
    int mode;           // the ringbuffer mode (blocking/overwrite)
};

/**
 * @brief Opaque structure representing a ringbuffer handler
 */
typedef struct _rbuf_s rbuf_t;

/**
 * @brief Create a new ringbuffer
 * @param size : The size of the ringbuffer (in bytes)
 * @return     : A pointer to an initialized rbuf_t structure
 */
rbuf_t *bbpro_rbuf_create(int size);

void bbpro_rbuf_set_mode(rbuf_t *rbuf, rbuf_mode_t mode);
rbuf_mode_t bbpro_rbuf_mode(rbuf_t *rbuf);

/**
 * @brief Skip the specified amount of bytes
 * @param rbuf  : A valid pointer to a rbuf_t structure
 * @param size :Tthe number of bytes to skip
 */
void bbpro_rbuf_skip(rbuf_t *rbuf, int size);

/**
 * @brief Read the specified amount of bytes from the ringbuffer
 * @param rbuf  : A valid pointer to a rbuf_t structure
 * @param out  : A valid pointer initialized to store the read data
 * @param size : The amount of bytes to read and copy to the memory
 *               pointed by 'out'
 * @return     : The amount of bytes actually read from the ringbuffer
 */
int bbpro_rbuf_read(rbuf_t *rbuf, uint8_t *out, int size);
/**
 * @brief Write the specified amount of bytes into the ringbuffer
 * @param rbuf  : A valid pointer to a rbuf_t structure
 * @param in   : A pointer to the data to copy into the ringbuffer
 * @param size : The amount of bytes to be copied
 * @return     : The amount of bytes actually copied into the ringbuffer
 * @note       : The ringbuffer may not fit the entire buffer to copy so
 *               the returned value might be less than the input 'size'.
 *               The caller should check for the returned value and retry
 *               writing the remainder once the ringbuffer has been emptied
 *               sufficiently
 */
int bbpro_rbuf_write(rbuf_t *rbuf, uint8_t *in, int size);

/**
 * @brief Returns the total size of the ringbuffer (specified at creation time)
 * @param rbuf  : A valid pointer to a rbuf_t structure
 * @return the total amount of bytes that can be stored in the rbuf
 */
int bbpro_rbuf_size(rbuf_t *rbuf);

/**
 * @brief Returns the amount of bytes stored into the ringbuffer
 *        and available for reading
 * @param rbuf  : A valid pointer to a rbuf_t structure
 * @return the amount of bytes stored into the ringbuffer
 *         and available for reading
 */
int bbpro_rbuf_used(rbuf_t *rbuf);

/**
 * @brief Returns the amount of space left in the ringbuffer for writing
 * @note equivalent to: rbuf_size() - rbuf_used()
 * @param rbuf  : A valid pointer to a rbuf_t structure
 * @return the amount of bytes which is still possible to write into the ringbuffer
 *         until some data is consumed by a rbuf_read() operation
 */
int bbpro_rbuf_available(rbuf_t *rbuf);

/**
 * @brief Scan the ringbuffer untill the specific byte is found
 * @param rbuf   : A valid pointer to a rbuf_t structure
 * @param octet : The byte to search into the ringbuffer
 * @return the offset to the specified byte, -1 if not found
 */
int bbpro_rbuf_find(rbuf_t *rbuf, uint8_t octet);

/**
 * @brief Read until a specific byte is found or maxsize is reached
 * @param rbuf     : A valid pointer to a rbuf_t structure
 * @param octet   : The byte to look for before stopping
 * @param out     : A valid pointer initialized to store the read data
 * @param maxsize : The maximum amount of bytes that can be copied to
 *                  the memory pointed by 'out'
 * @return        : The amount of bytes actually read from the ringbuffer
 */
int bbpro_rbuf_read_until(rbuf_t *rbuf, uint8_t octet, uint8_t *out, int maxsize);

int bbpro_rbuf_move(rbuf_t *src, rbuf_t *dst, int len);
int bbpro_rbuf_copy(rbuf_t *src, rbuf_t *dst, int len);

/**
 * @brief Clear the ringbuffer by eventually skipping all the unread bytes (if any)
 * @param rbuf : A valid pointer to a rbuf_t structure
 */
void bbpro_rbuf_clear(rbuf_t *rbuf);

/**
 * @brief Release all resources associated to the rbuf_t structure
 * @param rbuf : A valid pointer to a rbuf_t structure
 */
void bbpro_rbuf_destroy(rbuf_t *rbuf);

#ifdef __cplusplus
}
#endif

#endif /*__DATATRANS_QUEUE_H*/

/******************* (C) COPYRIGHT 2017 Realtek Semiconductor Corporation *****END OF FILE****/

